home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / ptv3n5.zip / FPEX.CPP < prev    next >
C/C++ Source or Header  |  1992-09-20  |  4KB  |  121 lines

  1. /*==================================================================
  2.  fpex.cpp  --  Examples of how to use fpnum class [Listing #5]
  3.  Fixed point math
  4.  by Robert N. Goldrich
  5. ==================================================================*/
  6. #include <iostream.h>
  7. #include "fpnum.h"
  8.  
  9. struct point { int x, y ; } ;
  10. struct rect  {
  11.     point a, b ;
  12.     rect( int x1, int y1, int x2, int y2 )
  13.             { a.x=x1, a.y=y1, b.x=x2, b.y=y2 ; }
  14. } ;
  15.  
  16. struct scaler {
  17.     fpnum  ax, cx,      // horizontal scale factor & offset
  18.            ay, cy ;     // vertical scale factor & offset
  19.     void set_scale( const rect& logical, const rect& phys ) ;
  20.     void scale( point& p ) const ;
  21. } ;
  22.  
  23.  
  24. /*------------------------------------------------------------------
  25.                    xp2,yp2
  26.     +-----------------+         Physical Coordinates
  27.     |         xl2,yl2 |
  28.     |                 |
  29.     |    Logical      |
  30.     |                 |
  31.     | xl1,yl1         |
  32.     +-----------------+
  33.  xp1,yp1
  34.  
  35.  Here we want the lower-left and upper-right corners to map into one
  36.  another perfectly.  Using straight fixed-point math this would not
  37.  be possible due to truncation errors.  The following function
  38.  compensates for truncation errors when necessary.
  39. ------------------------------------------------------------------*/
  40. void scaler::set_scale( const rect& p/*hys*/, const rect& l/*og*/ )
  41. {
  42. #define  BAD_X_SCALE   ( ax*dxl - dxp ).peek()  // used in place of
  43. #define  BAD_Y_SCALE   ( ay*dyl - dyp ).peek()  // ( expression==0 )
  44.  
  45.     ax = cx = ay = cy = 0 ;
  46.  
  47.     int  dxp = p.b.x - p.a.x ;
  48.     int  dyp = p.b.y - p.a.y ;
  49.     int  dxl = l.b.x - l.a.x ;
  50.     int  dyl = l.b.y - l.a.y ;
  51.  
  52.     if( dxp==0 || dyp==0 || dxl==0 || dyl==0 ) {
  53.         return ;        // this is an error. just return
  54.     }
  55.  
  56.     ax = fpnum(dxp) / dxl ;             // nominal scale x
  57.     if( BAD_X_SCALE ) {                 // correction (see above)
  58.         int xinc = ( ( dxl < 0 ) ? -1 : 1 ) ;
  59.         ax.inc_by( xinc ) ;
  60.     }
  61.  
  62.     ay = fpnum(dyp) / dyl ;             // nominal scale y
  63.     if( BAD_Y_SCALE ) {                 // correction (see above)
  64.         int yinc = ( dyl < 0 ) ? -1 : 1 ;
  65.         ay.inc_by( yinc ) ;
  66.     }
  67.  
  68.     cx = p.a.x - ax * l.a.x ;           // offsets
  69.     cy = p.a.y - ay * l.a.y ;
  70.  
  71. #undef  BAD_X_SCALE
  72. #undef  BAD_Y_SCALE
  73. }
  74.  
  75. //------------------------------------------------------------------
  76.  
  77. void scaler::scale( point& p ) const
  78. {
  79.     p.x = round_to_int( ax * p.x + cx ) ;
  80.     p.y = round_to_int( ay * p.y + cy ) ;
  81. }
  82.  
  83. //------------------------------------------------------------------
  84.  
  85. void scale_report( const scaler& s, point p )
  86. {
  87.     cout << "Point (" << p.x << "," << p.y ;
  88.     s.scale( p ) ;
  89.     cout << ") scales into (" << p.x << "," << p.y << ")\n" ;
  90. }
  91.  
  92. //------------------------------------------------------------------
  93.  
  94. int main()
  95. {
  96. //-- Examples of how to use fpnums
  97.     fpnum  fpmax ;      fpmax.poke( FP_MAX ) ;
  98.     fpnum  fpmin ;      fpmin.poke( FP_MIN ) ;
  99.     cout << "Number of fraction bits: " << FP_FRCBITS << '\n' ;
  100.     cout << "Maximum fpnum          : " << fpmax << '\n' ;
  101.     cout << "Minimum fpnum          : " << fpmin << '\n' ;
  102.     cout << "--------------------------------------------------\n" ;
  103.  
  104.     fpnum  cc = fp_cos( 32 ) ;          // cosine of 32 degrees
  105.     fpnum  ss = fp_sin( 32 ) ;          // sine of 32 degrees
  106.     fpnum  one = cc * cc + ss * ss ;    // should equal 1
  107.     cout << "This should equal 1    : " << one << "  (almost!)\n" ;
  108.     cout << "The error is " << (1-one)*100 << " percent.\n" ;
  109.     cout << "--------------------------------------------------\n" ;
  110.  
  111.     rect  screen( 0, 0, 659, 479 ) ;
  112.     rect  vport( 20, 47, 999, 600 ) ;
  113.     scaler s ;
  114.     s.set_scale( screen, vport ) ;
  115.  
  116.     point p = { 20, 47 } ;          scale_report( s, p ) ;
  117.     p.x = 999, p.y = 600 ;          scale_report( s, p ) ;
  118.  
  119.     return 0 ;
  120. }
  121.